#ifndef STRUCTMESH_HPP
#define STRUCTMESH_HPP

#include "structMeshBase.hpp"
#include "structEdge.hpp"
#include "structEdges.hpp"
#include "structCell.hpp"
#include "structCells.hpp"

namespace hms {

template<>
class MeshTraits<StructMesh>
{
public:
	using VertexType = Matrix2Xs::ConstColXpr;
	using EdgeType   = StructEdge;
	using EdgesType  = StructEdges;
	using CellType   = StructCell;
	using CellsType  = StructCells;
	using SizeType   = const Array2i&;
};

class StructMesh : public StructMeshBase<StructMesh>
{
public:
	using Traits = MeshTraits<StructMesh>;

private:
	Matrix2Xs m_vertices;
	Array2i   m_size {0,0};

public:
	StructMesh() = default;

	/**
	 * @brief Constructs a new StructMesh from vertices and the number of cells
	 * in x- and y-direction. The number of ghost layers can optionally be
	 * specified.
	 * 
	 * @param vertices 
	 * @param nCellsX the number of cells in topological x-direction
	 * @param nCellsY the number of cells in topological x-direction
	 */
	StructMesh(
		Matrix2Xs&& vertices,
		Index nCellsX,
		Index nCellsY
	);

	StructMesh(
		Matrix2Xs&& vertices,
		Array2i size
	);

	auto vertices() const -> const Matrix2Xs&;

private:
	auto nCellsXImp() const -> Index;
	auto nCellsYImp() const -> Index;

	auto sizeImp() const -> SizeType;

	auto vertexImp(Index) const -> Traits::VertexType;

	auto domainAreaImp() const -> scalar;

	friend MeshBase;
	friend StructMeshBase;
};

}


#endif